<?php

namespace App\Http\Controllers\V1;

use App\Events\OrderComputedDistribution;
use App\Exceptions\CouponCodeUnavailableException;
use App\Http\Requests\ConfirmOrderRequest;
use App\Http\Requests\OrderRequest;
use App\Http\Requests\SeckillOrderRequest;
use App\Http\Resources\ConfirmCartOrderResource;
use App\Http\Resources\MemberCouponResource;
use App\Http\Resources\OrderDetailResource;
use App\Http\Resources\OrderListResource;
use App\Http\Resources\OrderResource;
use App\Models\Cart;
use App\Models\Coupon;
use App\Models\Order;
use App\Models\Product;
use App\Models\ProductSku;
use App\Service\ConfigService;
use App\Service\LogisticService;
use App\Service\MiniProgramService;
use App\Service\OrderService;
use App\Http\Controllers\Controller;
use App\Service\ProductService;
use App\Service\UserService;
use App\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class OrderController extends Controller
{

    public function confirmOrder(ConfirmOrderRequest $request, OrderService $orderService, UserService $userService, ConfigService $configService, ProductService $productService)
    {
        // 验证之后的数据
        $validated = $request->validated();

        // 获取我的优惠券
        $coupons = $userService->getMyCoupons($request->user());

        //初始邮费 和 订单总价
        $freight = $productTotal = 0;

        // 初始化商品数据
        $products = [];

        // 获取 最近下单地址
        $address = Auth::user()->orders()->orderBy('created_at','desc')->value('address');
        // 购物车结算
        if($validated['confirm_type'] == 1)
        {
            if (!is_array($validated['cart_id'])) {
                $validated['cart_id'] = explode(',', $validated['cart_id']);
            }

            // 获取购物车结算的数据
            $carts = Cart::with(['productSku','product'])->whereIn('id', $validated['cart_id'])->where('user_id', Auth::id())->get();
            if ($carts->isEmpty()) {
                return $this->failed('购物车不存在');
            }
            // 计算该购物车的总价
            $productTotal = $carts->sum(function ($cart) {
                return $cart['total'];
            });
            // 保证数据类型的一致性
            $productTotal = bcadd($productTotal,'0',2);

            // 计算优惠券是否满足当前订单金额的条件（不加任何其他的条件，单纯商品价格）
            if ($coupons->isNotEmpty() ) {
                $coupons = MemberCouponResource::collection($orderService->checkConfirmOrderPriceLgCouponPrice($productTotal,$coupons, $carts->pluck('product_id')->toArray()));
            }
            // 计算运费 (优惠券的优惠不计算在内)
            // 是否满邮
            if(!$configService->isFreightFree($productTotal)){ //不满邮按照邮费组合计算出邮费

                $productId = $carts->map(function ($item){
                    return $item->product->id;
                })->toArray();

                $freight = $orderService->getFreightPrice($productId);
            };

            // 最终格式化购物车的数据
            $products = ConfirmCartOrderResource::collection($carts);

        }else if($validated['confirm_type'] == 2)  // 立即购买
        {
            // 获取商品信息
            $product = $productService->getProduct($validated['product_id']);

            $sku = ProductSku::find($validated['sku_id']);
            // 计算价格
            $productTotal = bcmul($sku->price, $validated['amount'],2);
            // 计算运费 (优惠券的优惠不计算在内) 秒杀商品不计算邮费
            // 是否满邮
            if(!$configService->isFreightFree($productTotal) && $product->type != Product::TYPE_SECKILL){ //不满邮按照邮费组合计算出邮费 (如果商品的运费id为0就直接免邮不计算了)

                $freight = $orderService->getFreightPrice($validated['product_id']);
            };
            // 计算优惠券是否满足当前订单金额的条件（不加任何其他的条件，单纯商品价格）秒杀不支持优惠券
            if ($product->type != Product::TYPE_SECKILL && $coupons->isNotEmpty()) {
                $coupons = MemberCouponResource::collection($orderService->checkConfirmOrderPriceLgCouponPrice($productTotal,$coupons, [$validated['product_id']]));
            }else {
                $coupons = [];
            }
            // 直接组装数据
            $products[] = [
                'product_id'    => $product->id,
                'sku_id'        => $sku->id,
                'total'         => $productTotal,
                'amount'        => $validated['amount'],
                'price'         => $sku->price,
                'spec_sku_name' => $sku->spec_sku_name,
                'title'         => $product->title,
                'image'         => empty($sku->image) ? $product->image : $sku->image
            ];
        }
        return $this->success([
            'total_amount'         => $productTotal,
            'freight_price'        => $freight,
            'address'              => $address,
            'confirms'             => $products,
            'coupons'              => $coupons,
        ]);
    }

    /**
     * 用户下单
     *
     * @param OrderRequest $request
     * @param OrderService $orderService
     * @return mixed
     * @throws CouponCodeUnavailableException
     */
    public function store(OrderRequest $request, OrderService $orderService)
    {
        $user = $request->user();
        $address = $request->input('address');
        $totalAmount = $request->input('total_amount');
        $freightPrice = $request->input('freight_price',0);
        $coupon  = null;
        if ($coupon_id = $request->input('coupon_id')) {
            $coupon = Coupon::where('id', $coupon_id)->first();
            if (!$coupon) {
                throw new CouponCodeUnavailableException('优惠券不存在');
            }
        }
        try{
            $order = $orderService->store(
                $user,
                $address,
                $request->input('remark'),
                json_decode( $request->input('items'),true),
                $totalAmount,
                $freightPrice,
                $coupon
            );
        } catch (\Exception $exception) {
            return $this->failed($exception->getMessage());
        }
        return $this->success(new OrderResource($order));
    }

    /**
     * 秒杀订单
     *
     * @param SeckillOrderRequest $request
     * @param OrderService $orderService
     * @return mixed
     */
    public function seckill(SeckillOrderRequest $request, OrderService $orderService)
    {
        $user    = $request->user();
        $address = $request->input('address');
        $totalAmount = $request->input('total_amount');
        $remark = $request->input('remark');
        $sku   = ProductSku::find($request->input('sku_id'));

        $order = $orderService->seckill($user, $sku, $address, $totalAmount, $remark);
        return $this->success(new OrderResource($order));
    }


    /**
     * 获取我的订单列表
     *
     * @return mixed
     */
    public function orderList() {

        $orders = Order::with(['items','coupon'])
                ->where('user_id', Auth::id())
                ->whereIn('ship_status', [
                    Order::SHIP_STATUS_PENDING,
                    Order::SHIP_STATUS_AWAITING_PAYMENT,
                    Order::SHIP_STATUS_DELIVERED,
                    Order::SHIP_STATUS_RECEIVED,
                    Order::SHIP_STATUS_TIME_OUT,
                    Order::SHIP_STATUS_CANCEL,
                    Order::SHIP_STATUS_REFUND,
                ])
                ->where(function ($query) {
                    if (request()->input('ship_status')) {
                        $query->where('ship_status', request()->input('ship_status'));
                    }
                })
                ->where('cancel_delete', null)
                ->orderByDesc('created_at')
                ->paginate(10);

        return $this->success([
            'list' => OrderListResource::collection($orders),
            'total' => $orders->total(),
            'current' => $orders->currentPage(),
        ]);
    }

    /**
     * 用户取消订单（待付款）
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function cancelOrder() {
        if(request()->has('order_id')) {
            $order = Order::findOrFail(request()->order_id);
            $this->authorize('own', $order);
            if($order->ship_status == Order::SHIP_STATUS_AWAITING_PAYMENT &&
                $order->update(['closed' => true, 'ship_status' => Order::SHIP_STATUS_CANCEL])
            ) {
                return $this->message('取消成功');
            }
        }
        return $this->failed('只有待支付才能取消订单');
    }

    /**
     * 用户删除订单
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function deleteOrder() {
        if(request()->has('order_id')) {
            $order = Order::findOrFail(request()->order_id);
            $this->authorize('own', $order);
            if ($order->cancel_delete <> null) {
                return $this->failed('该订单已删除');
            }
            if($order->ship_status == Order::SHIP_STATUS_RECEIVED &&
                $order->update(['cancel_delete' => now(), 'closed' => true])
            ) {
                return $this->message('删除成功');
            }
        }
        return $this->failed('只有已完成才能删除订单');
    }

    /**
     * 用户退款（待发货状态）
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function refundOrder() {
        if(request()->has('order_id')) {
            $order = Order::findOrFail(request()->order_id);
            $this->authorize('own', $order);
            if ($order->ship_status != Order::SHIP_STATUS_PENDING) {
                return $this->failed('只允许待发货发起退款');
            }
            $order->total_amount;
            $res = app(MiniProgramService::class)->refund(
                $order->payment_sn,
                $order->order_sn,
                intval(bcmul($order->total_amount, 100)),
                intval(bcmul($order->total_amount, 100)),
                ['refund_desc' => '系统自动退款']
            );
            if ($res['result_code'] == 'FAIL') {
                return $this->failed($res['err_code_des']);
            }
            if($res && $order->update(['ship_status' => Order::SHIP_STATUS_REFUND])) {
                $order->refund()->create([
                    'refund_extra' => json_encode($res)
                ]);
                // 增加库存
                foreach ($order->items as $item) {
                    $item->productSku->addStock($item->amount);
                    if ($item->product->sold_count >= $item->amount) {
                        $item->product->decrement('sold_count', $item->amount);
                    } else {
                        $item->product->update(['sold_count' => 0]);
                    }
                }
                return $this->message('退款成功');
            }
        }
        return $this->failed('参数错误');
    }

    /**
     * 用户确认收货
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function receivedOrder() {
        if(request()->has('order_id')) {
            $order = Order::findOrFail(request()->order_id);
            $this->authorize('own', $order);
            if ($order->ship_status == Order::SHIP_STATUS_DELIVERED &&
                $order->update([
                    'ship_status' => Order::SHIP_STATUS_RECEIVED,
                    'confirmed_at' => now()
                ])
            ) {
                // 确认收货进行分销
                if (request()->member_id) {
                    // 补全分享到商品信息
                    $shared = User::find(request()->member_id);
                    if ($shared) {
                        event(new OrderComputedDistribution($order, $shared,2));
                    }
                }
                return $this->message('收货成功');
            } else {
                return $this->failed('您已经确认收货');
            }
        }
        return $this->failed('该订单数据异常');
    }

    /**
     * 获取订单详情
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function orderDetail()
    {
        $order = Order::with(['items'])->orderByDesc('created_at')
            ->where('id',request()->order_id)
            ->where('cancel_delete', null)
            ->firstOrFail();
        $this->authorize('own', $order);
        return $this->success(new OrderDetailResource($order));
    }


    /**
     * 物流信息
     *
     * @return mixed
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function logisticsDetail()
    {
        $order = Order::findOrFail(request()->order_id);
        $this->authorize('own', $order);
        $logistics = [];
        if (!is_null($order->logistics_code)) {
            $logisticsData = json_decode($order->logistics_code, true);
            $logistics = app(LogisticService::class)
                ->getLogistic($logisticsData['code'], $order->id);

        }
        return $this->success($logistics);
    }
}
